package com.xiaoyu.im.data;

import android.text.TextUtils;
import android.util.Log;

import com.xiaoyu.im.config.HttpConfig;
import com.xiaoyu.im.provider.ConversationManager;
import com.xiaoyu.base.data.UserInfoDataProvider;
import com.xiaoyu.base.event.NoReceiverJsonEvent;
import com.xiaoyu.im.datamodel.common.IMConstant;
import com.xiaoyu.im.IMLog;
import com.xiaoyu.im.datamodel.ConversationType;
import com.xiaoyu.im.datamodel.vendors.VendorConversationUnique;
import com.xiaoyu.base.net.request.JsonEventRequest;
import com.xiaoyu.net.request.RequestWithJsonDataReturn;

import in.srain.cube.util.CheckUtil;

import com.xiaoyu.base.utils.ListUtil;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import in.srain.cube.request.FailData;
import in.srain.cube.request.JsonData;
import in.srain.cube.request.RequestData;
import in.srain.cube.request.RequestDefaultHandler;
import in.srain.cube.util.CLog;
import in.srain.cube.util.StringUtil;
import io.reactivex.functions.Predicate;

public class ConversationData {

    public static void updateConversationMute(String chatId, boolean mute) {
        updateConversation(chatId, mute ? IMConstant.UpdateConversationAction.MUTE : IMConstant.UpdateConversationAction.UNMUTE);
        ConversationManager.getInstance().updateConversationMuteAsync(chatId, mute);
    }

    public static void updateConversation(String chatId, String action) {
        final RequestWithJsonDataReturn<JsonData> request = new RequestWithJsonDataReturn<>();
        final RequestData requestData = request.getRequestData();
        requestData.setRequestUrl(HttpConfig.IM_UPDATE_CHAT);
        requestData.addPostData("chat_id", chatId);
        requestData.addPostData("action", action);

        request.setRequestHandler(new RequestDefaultHandler<JsonData, JsonData>() {
            @Override
            public JsonData processOriginData(JsonData originData) {
                return originData;
            }
        });
        request.enqueue();
    }

    public static void createConversationSync(String toUid, String fromType) {
        CheckUtil.checkNotMain();
        final RequestWithJsonDataReturn<JsonData> request = new RequestWithJsonDataReturn<>();
        RequestData requestData = request.getRequestData().setRequestUrl(HttpConfig.IM_CREATE_CHAT);
        requestData.addQueryData("toUid", toUid);
        requestData.addQueryData("createFrom", fromType);
        request.setRequestHandler(new RequestDefaultHandler<JsonData, JsonData>() {
            @Override
            public JsonData processOriginData(JsonData originData) {
                JsonData json = originData.optJson("data");
                processConversationJsonList(Collections.singletonList(json));

                if (isInvalidConversationJson(json)) {
                    String desc = String.format("invalid json, detail=%s", json.toString());
                    IMLog.logNetError("fetch_conv_by_fuid", desc);
                }

                return originData;
            }

            @Override
            public void onRequestFail(FailData failData) {
                String desc = String.format("request fail, detail=%s", Log.getStackTraceString(failData.getException()));
                IMLog.logNetError("fetch_conv_by_fuid", desc);
            }
        });
        try {
            request.requestSync();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    public static boolean syncConversationListFromServer(Collection<String> chatIds) {
        Map<String, Object> params = new HashMap<>();
        params.put("chatIds", TextUtils.join(",", chatIds));

        List<JsonData> jsonDataList = getChatInfoList(params);
        if (ListUtil.isNullOrEmpty(jsonDataList)) {
            return false;
        }
        processConversationJsonList(jsonDataList);
        return true;
    }

    public static boolean syncConversationListFromServerByVendorUniques(Collection<VendorConversationUnique> uniques) {
        Map<String, Collection<VendorConversationUnique>> vendorTypeUniqueMap = ListUtil.convertToMultimap(uniques, unique -> unique.vendorType);
        for (Map.Entry<String, Collection<VendorConversationUnique>> entry : vendorTypeUniqueMap.entrySet()) {
            String vendorType = entry.getKey();
            Collection<VendorConversationUnique> vendorUniques = entry.getValue();

            Predicate<VendorConversationUnique> singleTypeFilter = unique -> unique.conversationType.equals(ConversationType.SINGLE);

            List<String> singleCids = ListUtil.convertToList(vendorUniques, singleTypeFilter, unique -> unique.vendorCid);

            Map<String, Object> params = new HashMap<>();
            params.put("vendorType", vendorType);
            params.put("accids", TextUtils.join(",", singleCids));

            List<JsonData> jsonDataList = getChatInfoList(params);
            if (ListUtil.isNullOrEmpty(jsonDataList)) {
                return false;
            }
            processConversationJsonList(jsonDataList);
        }
        return true;
    }

    private static List<JsonData> getChatInfoList(Map<String, ?> params) {
        CheckUtil.checkNotMain();
        final RequestWithJsonDataReturn<JsonData> request = new RequestWithJsonDataReturn<>();
        RequestData requestData = request.getRequestData().setRequestUrl(HttpConfig.IM_CHAT_INFO_LIST);
        requestData.addQueryData(params);

        AtomicReference<List<JsonData>> jsonDataListReference = new AtomicReference<>();
        request.setRequestHandler(new RequestDefaultHandler<JsonData, JsonData>() {
            @Override
            public JsonData processOriginData(JsonData originData) {
                List<JsonData> jsonList = originData.optJson("data").toList();
                jsonDataListReference.set(jsonList);
                return originData;
            }
        });
        try {
            request.requestSync();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return ListUtil.emptyIfNull(jsonDataListReference.get());
    }

    public static void processConversationJsonList(List<JsonData> serverJsonList) {
        final List<JsonData> userJsonList = new LinkedList<>();
        final List<JsonData> conversationJsonList = new LinkedList<>();

        for (JsonData item : serverJsonList) {
            if (isInvalidConversationJson(item)) {
                continue;
            }
            conversationJsonList.add(item);

            if (item.has("toUser")) {
                JsonData userJsonData = item.optJson("toUser");
                userJsonList.add(userJsonData);
            }
        }

        UserInfoDataProvider.getInstance().updateFromJsonList(userJsonList);
        ConversationManager.getInstance().updateFromJsonList(conversationJsonList);
    }

    public static boolean isInvalidConversationJson(JsonData jsonData) {
        final String chatId = jsonData.optString("chatId");
        final String userAccid = jsonData.optString("userAccid");
        final boolean invalid = StringUtil.isAnyEmpty(chatId, userAccid);
        if (invalid) {
            CLog.e(IMConstant.LOG_TAG, "invalid conversation json %s", jsonData);
        }
        return invalid;
    }
}
